﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using CXMLStudioIDE.BusinessLayer;
using CXMLStudioIDE.Common;
using CXMLStudioIDE.Common.Entities;
using CXMLStudioIDE.DataAccessLayer;
using CXMLStudioIDE.Forms;
using CXMLStudioIDE.Views;
using CXMLStudioIDE.WinFormsUI.CXMLStudioControls;

namespace CXMLStudioIDE.Presenters
{
    public class MainPresenter
    {
        private readonly IMainView view;

        public MainPresenter(IMainView view)
        {
            this.view = view;
            view.OnCXMLTreeNodeClick += OnCXMLTreeNodeClick;
            view.OnCXMLTreeNodeSelectionChange += OnCXMLTreeNodeSelectionChange;
            view.OnActiveDocumentChanged += OnActiveDocumentChanged;
            view.OnProjectExplorerNodeDoubleClick += OnProjectExplorerNodeDoubleClick;
            view.OnProjectExplorerKeyPress += OnProjectExplorerKeyPress;
            view.OnPropertyValueChanged += OnPropertyValueChanged;
            view.OnTreeViewUpdated += OnTreeViewUpdated;
            view.OnTreeNodeHover += OnTreeNodeHover;
            view.OnTreeViewMouseMove += OnTreeViewMouseMove;
            view.OnAddInstance += OnAddInstance;
            view.OnInstanceAdded += OnGoldInstanceAdded;
        }

        #region Events

        public void OnFormCompleted(object sender)
        {
            FormDesigner fd = sender as FormDesigner;
            if(fd != null && fd.RootBusinessEntity != null &&
                fd.RootBusinessEntity.TreeViewId > 0)
            {
                view.SelectSolutionExplorerNodeById(fd.RootBusinessEntity.TreeViewId);
            }
        }

        public void OnEntityDroppedInFormDesigner(object sender)
        {
            view.Context = DisplayContext.FormDesigner;
            var fd = sender as FormDesigner;
            if (fd != null)
            {
                BusinessEntity be = null;
                be = fd.RootBusinessEntity;
                Type EntityType = fd.EntityType;
                if (be != null)
                {
                    HandleTreeView(DisplayContext.FormDesigner, be, EntityType,null);
                    view.ShowTreeView();
                }
            }
        }

        public void OnGoldFormCompleted(object sender)
        {
            var gef = sender as GoldEntryForm;
            if (gef != null && gef.RootBusinessEntity != null &&
                gef.RootBusinessEntity.TreeViewId > 0)
            {
                view.SelectSolutionExplorerNodeById(gef.RootBusinessEntity.TreeViewId);
            }
        }

        public void OnGoldFormLoading(object sender)
        {
            view.Context = DisplayContext.GoldCXML;
            var gef = sender as GoldEntryForm;
            if (gef != null)
            {
                BusinessEntity be = null;
                be = gef.RootBusinessEntity;
                Type EntityType = gef.EntityType;
                if (be != null)
                {
                    HandleTreeView(DisplayContext.GoldCXML, be, EntityType,null);
                    view.ShowTreeView();
                }
            }
        }

        /** Event triggered when an entity instance has been added
         * to a Gold Form, we add the CXMLTreeNode to the calling node**/

        public void OnGoldInstanceAdded(object sender)
        {
            var gef = sender as GoldEntryForm;
            if (gef != null && gef.AddedCXMLNode != null)
            {
                view.CallingCXMLTreeNode.Nodes.Add(gef.AddedCXMLNode);
                gef.Select();
                gef.AddedCXMLNode.EnsureVisible();
                view.SetTreeViewSelectedNode(gef.AddedCXMLNode);
            }
        }

        private void OnPropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            PropertyDescriptor property = e.ChangedItem.PropertyDescriptor;
            var fpg = s as FilteredPropertyGrid;
            var propdal = new PropertiesDAL();
            CXMLTreeNode node = null;
            Control ctrl = null;
            Type t = null;
            ControlType ctrl_type = ControlType.Control;
            DisplayContext context = DisplayContext.Deafult;
            int i_EntityTypeVersionsID = -1;

            if (fpg != null && property != null)
            {
                t = fpg.SelectedObject.GetType();
                if (Common.Common.IsSubclassOfRawGeneric(typeof (Control), t))
                {
                    t = typeof (Control);
                }
                else if (t.Name.Equals("CXMLTreeNode"))
                {
                    node = fpg.SelectedObject as CXMLTreeNode;
                }
            }

            switch (MainForm.m_currentcontext)
            {
                case DisplayContext.FormDesigner:
                    switch (t.Name)
                    {
                        case "Control":
                            ctrl = (Control) fpg.SelectedObject;
                            if (ctrl != null)
                            {
                                string lineage = Common.Common.GetLineageFromControlName(ctrl.Name);
                                i_EntityTypeVersionsID = CXMLTreeNode.GetEntityTypeVersionsIdFromLineage(ctrl.Name);
                                if (lineage != null && i_EntityTypeVersionsID > 0)
                                {
                                    var propBL = new PropertiesBL();
                                    propBL.SaveControlBinaryProperties(ctrl, i_EntityTypeVersionsID, lineage,
                                                                       DisplayContext.FormDesigner, ControlType.Control);
                                }
                            }
                            break;
                        case "CXMLTreeNode":
                            context = DisplayContext.FormDesigner;
                            ctrl_type = ControlType.CXMLTreeNode;
                            break;
                    }

                    break;
                case DisplayContext.Deafult:
                    context = DisplayContext.Deafult;
                    ctrl_type = ControlType.CXMLTreeNode;
                    break;
                case DisplayContext.GoldCXML:
                    context = DisplayContext.GoldCXML;
                    ctrl_type = ControlType.CXMLTreeNode;
                    break;
            }
            if (node != null)
            {
                SaveProperty(context, ctrl_type, node);
            }
        }

        /** Handles the event triggered when adding Gold instances to TreeView 
         * Open TreeView and then in OnTreeViewUpdated builds the GoldForm
         * for the added entity. Keep track of Calling Gold Form*/

        private void OnAddInstance(object sender, AddInstanceArgs args)
        {
            if (args.BusinessEntity != null)
            {
                //view.AddInstanceTreeToNode(args.BusinessEntity, args.ParentNode);
                //Keep track of the calling Gold Form and calling CXMLTreeNode
                view.CallingGoldForm = args.CallingGoldForm;
                view.CallingCXMLTreeNode = args.CallingNode;
                view.MyAddInstanceMode = args.Mode;
                HandleTreeView(DisplayContext.GoldCXML, args.BusinessEntity,null,null);
                view.ShowTreeView();
            }
        }

        private void SaveProperty(DisplayContext context, ControlType ctrl_type, CXMLTreeNode node)
        {
            if (node != null && node.Lineage != null && node.BusinessEntity != null)
            {
                var propBL = new PropertiesBL();
                propBL.SaveControlBinaryProperties(node, node.BusinessEntity.EntityTypeVersions.EntityTypeVersionsID,
                                                   node.Lineage, context, ctrl_type);
            }
        }

        private void OnProjectExplorerKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char) 13)
            {
                TreeNode node = view.ProjectExplorerSelectedNode;
                if (node != null)
                {
                    OnProjectExplorerNodeDoubleClick(sender,
                                                     new TreeNodeMouseClickEventArgs(node, MouseButtons.Left, 0, 0, 0));
                }
            }
        }

        private void OnProjectExplorerNodeDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (!e.Node.Text.StartsWith("Business Entities") && e.Node.Level > 1)
            {
                ((MainForm) view).Cursor = Cursors.WaitCursor;
                view.ShowTreeView();
                BusinessEntityCollection bec =
                    ((MainForm) view).m_SolutionManager.m_solution.GetBusinessEntitiesInSolution();
                BusinessEntity b = bec.GetBusinessEntityByTreeViewID(Convert.ToInt32(e.Node.Name));
                if (b != null)
                {
                    HandleTreeView(DisplayContext.Deafult, b, null,null);
                }
                ((MainForm) view).Cursor = Cursors.Default;
            }
        }

        private void OnTreeViewUpdated(object o, TreeviewWorkerArgs args)
        {
            if (args != null)
            {
                if (args.DisplayContext == DisplayContext.Deafult)
                {
                    view.UpdateDataDictionary(args.BusinessEntity);
                    view.ShowDataDictionary();
                    BusinessEntity b = view.GetCurrentTreeViewBusinessEntity();
                    if (b != null)
                    {
                        view.SelectSolutionExplorerNodeById(b.TreeViewId);
                    }
                }
                view.ShowTreeView();
                view.StopTreeViewProgressBar();
                /*If The TreeView was loaded from Adding a new gold instance then
                 * open new gold form **/
                if (view.CallingGoldForm != null && view.CurrentRootNode != null)
                {
                        view.NewGoldEntryForm(view.CurrentRootNode, view.CallingGoldForm,
                            view.CallingCXMLTreeNode,view.MyAddInstanceMode);
                }
                view.CallingGoldForm = null;
            }
        }

        public void OnTreeNodeHover(object o, TreeNodeMouseHoverEventArgs e)
        {
            var tv = o as CXMLTreeView;
            var node = e.Node as CXMLTreeNode;
            Form ActiveForm = ((MainForm) view).ActiveMdiChild;
            if (node != null)
            {
                switch (view.Context)
                {
                    case DisplayContext.GoldCXML:
                        var gef = ActiveForm as GoldEntryForm;
                        if (!string.IsNullOrEmpty(node.GoldInstanceDescription) &&
                            view.TreeViewToolTipText != node.GoldInstanceDescription)
                        {
                            view.TreeViewToolTipText = node.GoldInstanceDescription;
                            break;
                        }
                        if (gef != null && node.Lineage != null)
                        {
                            string tooltiptext = node.Text + " Value: [" +
                            gef.GetValueByBindingName(gef.EntityInstance, node.BindingName) +
                            "]";
                            view.TreeViewToolTipText = tooltiptext;
                        }
                        break;
                }
            }
            else
            {
                view.TreeViewToolTipText = "";
            }
        }

        /** Display the value of control in the form correspondingn to the
         * treenode below the mouse pointer only in Gold context**/

        public void OnTreeViewMouseMove(object sender, MouseEventArgs e)
        {
            var tv = sender as CXMLTreeView;
            var node = tv.GetNodeAt(e.X, e.Y) as CXMLTreeNode;
            Form ActiveForm = ((MainForm) view).ActiveMdiChild;
            if (node != null)
            {
                switch (view.Context)
                {
                    case DisplayContext.GoldCXML:
                        var gef = ActiveForm as GoldEntryForm;
                        if (!string.IsNullOrEmpty(node.GoldInstanceDescription) &&
                            view.TreeViewToolTipText != node.GoldInstanceDescription)
                        {
                            view.TreeViewToolTipText = node.GoldInstanceDescription;
                        }
                        else
                        {
                            if (gef != null && node.Lineage != null)
                            {
                                //string tooltiptext = node.Text + " Value: [" + gef.GetValueByLineage(node.Lineage) + "]";
                                string tooltiptext = node.Text + " Value: [" +
                                                     gef.GetValueByBindingName(gef.EntityInstance, node.BindingName) +
                                                     "]";
                                // Change the ToolTip only if the pointer moved to a new node.
                                if (view.TreeViewToolTipText != tooltiptext)
                                {
                                    view.TreeViewToolTipText = tooltiptext;
                                }
                            }
                            else
                            {
                                view.TreeViewToolTipText = "";
                            }
                        }
                        break;
                }
            }
            else
            {
                view.TreeViewToolTipText = "";
            }
        }

        private void OnCXMLTreeNodeSelectionChange(object sender, TreeViewEventArgs e)
        {
            Form ActiveForm = ((MainForm) view).ActiveMdiChild;
            var node = e.Node as CXMLTreeNode;
            if (node != null)
            {
                switch (view.Context)
                {
                    case DisplayContext.FormDesigner:
                        if (ActiveForm != null && node.BusinessEntity != null)
                        {
                            var fd = ActiveForm as FormDesigner;
                            if (fd != null && fd.RootBusinessEntity.Equals(node.BusinessEntity.Parent))
                            {
                                fd.SelectByLineage(node.Lineage);
                            }
                            view.PropertyGridSelectedObject = node;
                        }
                        break;
                    case DisplayContext.GoldCXML:
                        if (ActiveForm != null && node.BusinessEntity != null)
                        {
                            var gef = ActiveForm as GoldEntryForm;
                            if (gef != null && gef.RootBusinessEntity.Equals(node.BusinessEntity.Parent))
                            {
                                gef.SelectByLineage(node.Lineage, false);
                            }
                            view.PropertyGridSelectedObject = node;
                        }
                        break;
                    case DisplayContext.Deafult:
                        if (node.BusinessEntity != null)
                        {
                            view.UpdateDataDictionary(node.BusinessEntity);
                            view.SetFocusOnTreeView(node);
                            view.PropertyGridSelectedObject = node;
                        }
                        if (ActiveForm == null || ActiveForm.ActiveMdiChild == null ||
                            ActiveForm.Name.Equals("DataDictionaryForm"))
                        {
                            view.ShowDataDictionary();
                        }
                        break;
                }
            }
        }

        private void OnCXMLTreeNodeClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            Form ActiveForm = ((MainForm) view).ActiveMdiChild;
            var node = e.Node as CXMLTreeNode;
            if (node != null)
            {
                switch (view.Context)
                {
                    case DisplayContext.GoldCXML:
                        var gef = ActiveForm as GoldEntryForm;
                        if (gef != null && node.BusinessEntity != null)
                        {
                            if (gef.RootBusinessEntity.Equals(node.BusinessEntity.Parent))
                            {
                                gef.SelectByLineage(node.Lineage, true);
                            }
                        }
                        break;
                }
                view.PropertyGridSelectedObject = node;
            }
        }

        private void OnActiveDocumentChanged(object sender, EventArgs e)
        {
            ((MainForm) view).Cursor = Cursors.WaitCursor;
            Form ActiveForm = ((MainForm) view).ActiveMdiChild;
            //Set the current context based on the active mdichild form.
            if (ActiveForm != null)
            {
                switch (ActiveForm.Name)
                {
                    case "FormDesigner":
                        view.Context = DisplayContext.FormDesigner;
                        view.TreeViewWindowTitle = "TreeView - Form Designer";
                        var fd = ActiveForm as FormDesigner;
                        if (fd != null)
                        {
                            /** When changing to other Form Designer Tab
                             * Then show the corresponding TreeView **/
                            BusinessEntity be = null;
                            be = fd.RootBusinessEntity;
                            Type EntityType = fd.EntityType;
                            if (be != null)
                            {
                                view.SelectSolutionExplorerNodeById(be.TreeViewId);
                                HandleTreeView(DisplayContext.FormDesigner, be, EntityType,null);
                            }
                        }
                        break;
                    case "GoldEntry":
                        view.Context = DisplayContext.GoldCXML;
                        view.TreeViewWindowTitle = "TreeView - Gold Entry Form";
                        var gef = ActiveForm as GoldEntryForm;
                        if (gef != null)
                        {
                            BusinessEntity be = null;
                            be = gef.RootBusinessEntity;
                            Type EntityType = gef.EntityType;
                            if (be != null)
                            {
                                view.SelectSolutionExplorerNodeById(be.TreeViewId);
                                HandleTreeView(DisplayContext.GoldCXML, be, EntityType,null);
                                //view.ShowTreeView();
                            }
                        }
                        break;
                    case "DataDictionaryForm":
                        view.Context = DisplayContext.Deafult;
                        view.TreeViewWindowTitle = "TreeView - Default";
                        BusinessEntity b = view.GetCurrentTreeViewBusinessEntity();
                        if (b != null)
                        {
                            view.SelectSolutionExplorerNodeById(b.TreeViewId);
                            view.UpdateDataDictionary(b);
                            HandleTreeView(DisplayContext.Deafult, b, null,null);
                            //view.ShowTreeView();
                        }
                        break;
                    default:
                        view.TreeViewWindowTitle = "TreeView - Default";
                        break;
                }
            }
            ((MainForm) view).Cursor = Cursors.Default;
        }

        /** Check if TreeView is alrady in hashtable, if not add it **/

        private void HandleTreeView(DisplayContext context, BusinessEntity be, Type EntityType,object instance)
        {
            view.LoadTreeView(be, context, EntityType,instance);
        }

        #endregion
    }
}